Skip to content

Conversation

bilhox
Copy link
Contributor

@bilhox bilhox commented Aug 31, 2024

Implementation of #1242 according to MyreMylar name proposal.

While I'm bringing this feature to a potential release, what's your opinion on rel_centerx and rel_centery ?

Closes #1242 .

Tests + documentation added.

@bilhox bilhox requested a review from a team as a code owner August 31, 2024 22:11
@damusss
Copy link
Member

damusss commented Sep 1, 2024

I'm not sure about the x and y variants, as
(r.w/2+N, r.h/2+M) is shorter than (r.rel_centerx+N, r.rel_centery+M) (where N and M are arbitrary numbers not to make the expression useless), but I like rel_center, it makes sense.

@damusss damusss added New API This pull request may need extra debate as it adds a new class or function to pygame rect pygame.rect labels Sep 1, 2024
@aatle
Copy link
Contributor

aatle commented Sep 2, 2024

rel_centerx and rel_centery are probably less readable than width/2, and less useful compared to centerx.

It seems to me like most uses would be related to Surfaces.
I think more concrete use cases for this feature need to be listed.

@bilhox
Copy link
Contributor Author

bilhox commented Sep 3, 2024

rel_centerx and rel_centery are probably less readable than width/2, and less useful compared to centerx.

It seems to me like most uses would be related to Surfaces. I think more concrete use cases for this feature need to be listed.

With the argument you gave with damus, indeed rel_centerx and rel_centery is not needed.
Except that, I think the person who opened the issue gave a fairly good usecase, and I personally support the feature for the same reason.

@aatle
Copy link
Contributor

aatle commented Sep 4, 2024

I agree that the feature is logical and should probably be implemented, but I wonder if there are more use cases than the one given:

I often find myself evaluating (rect.w / 2, rect.h / 2) to find the middle of a rect, relative to itself. This is useful when drawing a circle onto a surface for a sprite, for example.

If I understand this case correctly, one could use surface.get_rect().center instead, right? For rects from surfaces, the position is (0,0) since only size is relevant, so rel_center is not needed.
I personally don't see any use cases in my own project codebase, but that's probably because I use Vector2 for this stuff.

Copy link
Member

@MyreMylar MyreMylar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rename it relcenter ? Then I think we can get this in.

@Starbuck5 Starbuck5 changed the title Implementation of pygame.(F)Rect.rel_center Implementation of pygame.(F)Rect.relcenter Jan 1, 2025
@ankith26 ankith26 marked this pull request as draft June 7, 2025 18:45
Copy link
Contributor

coderabbitai bot commented Aug 26, 2025

📝 Walkthrough

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@MyreMylar MyreMylar marked this pull request as ready for review August 26, 2025 19:18
@MyreMylar MyreMylar requested review from damusss and aatle August 26, 2025 19:19
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/reST/ref/rect.rst (1)

61-63: Docs correctness: mention that assigning relcenter resizes (it’s an exception to “all other assignments move”).

Currently the paragraph says only size/width/height resize; with relcenter added, that statement is no longer accurate. Also, minor style nits in the example and rounding wording.

Apply these doc tweaks:

-   Assigning to size, width or height changes the dimensions of the rectangle;
-   all other assignments move the rectangle without resizing it. Notice that
+   Assigning to ``size``, ``width``, ``height``, or ``relcenter`` changes the
+   dimensions of the rectangle. Assigning to ``relcenter`` resizes the rect
+   around its top-left (the top-left remains unchanged). All other assignments
+   move the rectangle without resizing it. Notice that
    some attributes are integers and others are pairs of integers.

And in the versionadded block:

-      .. code-block:: python
-
-         > my_rect = pygame.Rect(0, 0, 2, 2)
-         > my_rect.relcenter
-         > (1, 1)
-         > my_rect.relcenter = (128, 128)
-         > my_rect.relcenter, my_rect.size
-         > ((128, 128), (256, 256))
+      .. code-block:: python
+
+         >>> my_rect = pygame.Rect(0, 0, 2, 2)
+         >>> my_rect.relcenter
+         (1, 1)
+         >>> my_rect.relcenter = (128, 128)
+         >>> (my_rect.relcenter, my_rect.size)
+         ((128, 128), (256, 256))

And clarify rounding precisely (Rect truncates toward zero):

-      Beware of non integer relative centers ! Using a Rect instead of FRect will round down
-      the values of the returned ``Point``.
+      Beware of non-integer relative centers! With ``Rect`` (integer sizes),
+      halves are truncated toward zero; with ``FRect`` (float sizes), halves preserve
+      fractional parts.

Also applies to: 96-113

🧹 Nitpick comments (4)
test/rect_test.py (3)

581-587: Fix test docstring: says “center” but the test is for relcenter.

Apply:

-        """Ensures the center attribute can't be deleted."""
+        """Ensures the relcenter attribute can't be deleted."""

909-916: Reduce test duplication around expected relcenter calculations.

A small helper would de-duplicate the repeated expected_new_relcenter math and assertions across scale/inflate variants, improving readability and maintenance.

Example helper (define near other test utilities):

def _assert_relcenter(self, r, expected):
    self.assertEqual(expected, r.relcenter if isinstance(r.relcenter[0], int) else tuple(expected))

Then reuse:

expected_new_relcenter = (r.w, r.h * 2)
self._assert_relcenter(r2, expected_new_relcenter)

Also applies to: 924-931, 940-947, 955-972, 973-995, 1001-1016, 1017-1034, 1043-1051, 1052-1059, 1061-1068, 1069-1076, 1078-1085, 1138-1149, 1154-1165, 1178-1191


3111-3126: Consider adding a direct setter test for FRect.relcenter.

You verify FRect relcenter reads and many transforms, but not the explicit setter. Add one case to ensure floats are preserved and topleft remains unchanged.

Suggested test:

def test_frect_relcenter_setter(self):
    r = FRect(1.25, 2.5, 3.5, 4.75)
    old_tl = r.topleft
    r.relcenter = (12.8, 7.6)
    self.assertSeqAlmostEqual5(old_tl, r.topleft)
    self.assertSeqAlmostEqual5((12.8, 7.6), r.relcenter)
    self.assertSeqAlmostEqual5((25.6, 15.2), r.size)
src_c/rect_impl.h (1)

2839-2864: Minor comment label and rounding behavior note.

  • The block header reads “/center/”; rename to “/* relcenter */” for clarity.
  • Optional: If you want docs to be exact, note that integer division truncates toward zero (already addressed in docs suggestion).

Apply:

-/*center*/
+/* relcenter */
 static PyObject *
 RectExport_getrelcenter(RectObject *self, void *closure)
 {
     return TupleFromTwoPrimitives(self->r.w / 2, self->r.h / 2);
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f46a4b6 and a47a9f9.

📒 Files selected for processing (5)
  • buildconfig/stubs/pygame/rect.pyi (1 hunks)
  • docs/reST/ref/rect.rst (2 hunks)
  • src_c/rect.c (4 hunks)
  • src_c/rect_impl.h (4 hunks)
  • test/rect_test.py (26 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src_c/rect.c (1)
src_c/rect_impl.h (2)
  • RectExport_getrelcenter (2840-2844)
  • RectExport_setrelcenter (2846-2864)
test/rect_test.py (1)
buildconfig/stubs/pygame/rect.pyi (9)
  • Rect (307-307)
  • relcenter (99-99)
  • relcenter (101-101)
  • x (39-39)
  • x (41-41)
  • y (43-43)
  • y (45-45)
  • scale_by (175-175)
  • scale_by (177-177)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: x86_64
  • GitHub Check: aarch64
  • GitHub Check: i686
  • GitHub Check: x86_64
  • GitHub Check: debug_coverage (ubuntu-24.04, 3.13.5)
  • GitHub Check: debug_coverage (ubuntu-24.04, 3.14.0rc1)
  • GitHub Check: debug_coverage (ubuntu-24.04, 3.9.23)
  • GitHub Check: x86
  • GitHub Check: AMD64
  • GitHub Check: Debian (Bookworm - 12) [armv7]
  • GitHub Check: Debian (Bookworm - 12) [armv6]
  • GitHub Check: Debian (Bookworm - 12) [s390x]
  • GitHub Check: Debian (Bookworm - 12) [ppc64le]
  • GitHub Check: msys2 (ucrt64, ucrt-x86_64)
  • GitHub Check: msys2 (clang64, clang-x86_64)
  • GitHub Check: msys2 (mingw64, x86_64)
  • GitHub Check: build (ubuntu-24.04)
  • GitHub Check: build (ubuntu-22.04)
  • GitHub Check: dev-check
🔇 Additional comments (8)
buildconfig/stubs/pygame/rect.pyi (1)

99-101: relcenter property stub looks correct and consistent.

  • Naming matches existing style (center/centerx/centery).
  • Types align with other position/size properties (getter returns tuple[_N, _N]; setter accepts Point).
docs/reST/ref/rect.rst (2)

50-50: Public attribute list update is good.

Adding “relcenter” right after “center” mirrors the API surface and helps discoverability.


96-96: Version marker sanity check.

Please confirm the correct release number for this addition (currently “2.5.6”). If this lands in a different tag, update accordingly.

src_c/rect.c (2)

136-137: C API mappings for relcenter are wired correctly.

The Rect/FRect macro aliases match the template implementation names; no symbol drift spotted.

Also applies to: 255-256


692-694: Property exposure: placement and signature look good.

  • relcenter follows center in both getset tables (Rect and FRect), matching docs and stubs.
  • NULL doc strings consistent with other attributes.

Also applies to: 736-738

test/rect_test.py (1)

559-572: Good coverage for relcenter basic semantics.

  • Verifies resize-while-anchoring topleft and round-trip readback. Solid.
src_c/rect_impl.h (2)

287-293: Template guards include relcenter—good.

The new guards mirror existing center/size guards and protect both getter and setter; consistent with the template pattern.


614-617: Prototype declarations for relcenter align with template usage.

Signatures match other tuple-based accessors; no ABI surprises.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
test/rect_test.py (2)

3426-3434: Prefer almost-equal for float centers to avoid flakiness

Use the existing helper for r.center vs r2.center to match the rest of the FRect tests.

Apply this diff:

-        self.assertEqual(r.center, r2.center)
+        self.assertSeqAlmostEqual5(r.center, r2.center)

3123-3126: Consider adding setter tests for FRect.relcenter and float inputs for Rect.relcenter

Would close gaps by asserting:

  • FRect: setting relcenter preserves topleft and sets size to 2*value (floats).
  • Rect: setting relcenter with floats coerces/truncates as per other attributes.

If helpful, I can draft concise tests covering these two cases.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a47a9f9 and 380ad24.

📒 Files selected for processing (3)
  • docs/reST/ref/rect.rst (3 hunks)
  • src_c/rect_impl.h (4 hunks)
  • test/rect_test.py (26 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src_c/rect_impl.h
  • docs/reST/ref/rect.rst
🧰 Additional context used
🧬 Code graph analysis (1)
test/rect_test.py (1)
buildconfig/stubs/pygame/rect.pyi (25)
  • Rect (307-307)
  • left (51-51)
  • left (53-53)
  • top (47-47)
  • top (49-49)
  • relcenter (99-99)
  • relcenter (101-101)
  • topleft (63-63)
  • topleft (65-65)
  • size (111-111)
  • size (113-113)
  • w (123-123)
  • w (125-125)
  • h (127-127)
  • h (129-129)
  • centerx (103-103)
  • centerx (105-105)
  • x (39-39)
  • x (41-41)
  • y (43-43)
  • y (45-45)
  • scale_by (175-175)
  • scale_by (177-177)
  • centery (107-107)
  • centery (109-109)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: x86_64
  • GitHub Check: x86_64
  • GitHub Check: aarch64
  • GitHub Check: i686
  • GitHub Check: msys2 (ucrt64, ucrt-x86_64)
  • GitHub Check: msys2 (mingw64, x86_64)
  • GitHub Check: msys2 (clang64, clang-x86_64)
  • GitHub Check: x86
  • GitHub Check: AMD64
  • GitHub Check: Debian (Bookworm - 12) [armv7]
  • GitHub Check: Debian (Bookworm - 12) [armv6]
  • GitHub Check: Debian (Bookworm - 12) [s390x]
  • GitHub Check: Debian (Bookworm - 12) [ppc64le]
  • GitHub Check: build (ubuntu-22.04)
  • GitHub Check: debug_coverage (ubuntu-24.04, 3.14.0rc1)
  • GitHub Check: build (ubuntu-24.04)
  • GitHub Check: build (windows-latest)
  • GitHub Check: debug_coverage (ubuntu-24.04, 3.9.23)
  • GitHub Check: debug_coverage (ubuntu-24.04, 3.13.5)
  • GitHub Check: dev-check
🔇 Additional comments (25)
test/rect_test.py (25)

559-587: Relcenter basics: getter/setter, validation, and deletion look correct

Setting relcenter resizes from topleft as intended; invalid types and deletion are handled consistently with other Rect attrs. Nice coverage.


866-876: LGTM: relcenter tracks inflate(-x, -y) for Rect

Expected relcenter uses integer halves after size change; assertions match center-preserving semantics.


898-908: LGTM: relcenter tracks inflate_ip(-x, -y) for Rect

Correct integer math and invariants.


913-923: LGTM: scale_by(2) updates relcenter to previous size

Relcenter equals (new_w//2, new_h//2) = old size; assertions are consistent.


929-939: LGTM: scale_by(x=2) single-arg kw path

Same expectations as positional; good redundancy.


944-954: LGTM: scale_by(0.5) halves relcenter

Integer floor semantics captured via // for Rect.


962-972: LGTM: scale_by(2, 4) mixed scaling

Relcenter expectation (w, h*2) is correct; edges/center assertions align.


985-995: LGTM: scale_by(scale_by=(2, 4)) kwargs variant

Covers tuple-arg path; math checks out.


1006-1016: LGTM: scale_by(x=2, y=4) kw variant

Relcenter and bounds assertions are sound.


1024-1034: LGTM: scale_by(0.5, 0.25) downscale

Correct use of // for integer Rect semantics.


1043-1085: LGTM: subzero and negative factors handling

Relcenter expectations for large/negative scales are consistent and symmetric; good regression coverage.


1139-1149: LGTM: scale_by_ip(2) in-place doubles relcenter

In-place path mirrors functional variant; assertions consistent.


1155-1165: LGTM: scale_by_ip(0.5) in-place halves relcenter

Covers integer rounding correctly.


1181-1191: LGTM: scale_by_ip(x=2, y=4) kwargs

Relcenter and bounds preserved; nice coverage of kw path.


3123-3133: LGTM: FRect relcenter equals (w/2, h/2) with float semantics

Baseline expectation verified alongside center and midpoints.


3153-3164: LGTM: FRect scale_by(2.3) relcenter math

Uses 1.15 factor; tolerances handled via AlmostEqual5 helper.


3170-3181: LGTM: FRect scale_by(x=2.3) kw

Duplicate path validated with float assertions.


3186-3196: LGTM: FRect scale_by(0.5)

Expected relcenter fractions and bounds deltas look right.


3204-3214: LGTM: FRect scale_by(2, 4)

Relcenter components (w, 2h) are correct; center preserved.


3227-3237: LGTM: FRect scale_by(scale_by=(2, 4))

Covers tuple kw path; assertions consistent.


3248-3258: LGTM: FRect scale_by(x=2, y=4)

Relcenter and bounds checks are sound.


3266-3276: LGTM: FRect scale_by(0.5, 0.25)

Downscale expectations (0.25w, 0.125h) correctly asserted.


3285-3330: LGTM: FRect subzero/negative scaling suite

Robust coverage of sign invariance and axis-specific scaling; relcenter expectations match new half-sizes.


3383-3394: LGTM: FRect scale_by_ip(2.3)

In-place behavior mirrors non-inplace; float tolerance applied.


3400-3410: LGTM: FRect scale_by_ip(0.5)

Relcenter and bounds verified with float tolerance.

Copy link
Contributor

@aatle aatle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@aatle aatle added this to the 2.5.6 milestone Aug 30, 2025
@aatle aatle merged commit 83d395f into pygame-community:main Aug 30, 2025
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
New API This pull request may need extra debate as it adds a new class or function to pygame rect pygame.rect
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Rect.size_rect (2429)
5 participants